package WWW::NikePlus::Challenge;

use strict;
use XML::LibXML;

use constant {
  DETAIL_URL =>
'https://secure-nikeplus.nike.com/nikeplus/v2/services/app/get_challenge_detail_information.jsp',
  MEMBER_URL =>
'https://secure-nikeplus.nike.com/nikeplus/v2/services/app/get_challenge_member_list.jsp',
};

our $VERSION = '0.01';

sub new {
  my $class = shift(@_);
  my $self  = {@_};

  foreach my $required (qw{ user_agent challenge_name summary }) {
    die(__PACKAGE__ . "::new requires parameter: [$required]\n")
      unless(exists($self->{$required}));
  }

  $self->{'xp'} = XML::LibXML->new();

  $self = bless($self, $class);

  $self->_initialize();

  return $self;
}

sub _initialize {
  my ($self) = @_;

  my $ref = $self->{'summary'};
  $self->{'active'}       = ($ref->{'active'} eq 'true');
  $self->{'type'}         = $ref->{'definition'}{'type'};
  $self->{'group'}        = $ref->{'definition'}{'type'} =~ /^group/io;
  $self->{'membercount'}  = $ref->{'challengeMemberCount'};
  $self->{'starttime'}    = $ref->{'startTime'};
  $self->{'endtime'}      = $ref->{'endTime'};
  $self->{'challenge_id'} = $ref->{'id'};
  $self->{'description'}  = $ref->{'greeting'};

  delete($self->{'summary'});
}

sub isActive       { return $_[0]->{'active'}; }
sub getDescription { return $_[0]->{'description'}; }
sub getName        { return $_[0]->{'challenge_name'}; }
sub getID          { return $_[0]->{'challenge_id'}; }
sub isTeam         { return $_[0]->{'group'}; }
sub getStartTime   { return $_[0]->{'starttime'}; }
sub getEndTime     { return $_[0]->{'endtime'}; }
sub getMemberCount { return $_[0]->{'membercount'}; }
sub getType        { return $_[0]->{'type'}; }

sub getRank {
  my ($self) = @_;

  $self->getMembers() if(!exists($self->{'rank'}));
  return $_[0]->{'rank'};
}

sub getTeams {
  my ($self) = @_;

  $self->getDetail()
    if(!exists($self->{'teams'}));
  return $self->{'teams'};
}

sub getTeam {
  my ($self) = @_;

  $self->getDetail()
    if(!exists($self->{'teams'}));
  return $_[0]->{'teams'}{$_[0]->{'team'}};
}

sub getTeamRank {
  my ($self) = @_;

  my $team = $self->getTeam();
  return $self->isTeam() ? $team->{'rank'} : undef;
}

sub getDetail {
  my ($self) = @_;

  if(!exists($self->{'details'})) {
    my $doc = $self->_request(DETAIL_URL . "?id=$self->{'challenge_id'}");
    $self->{'details'} = 1;

    my ($node) = $doc->findnodes('//userInfo/groupID/text()');

    if($node) {
      $self->{'team'} = $node->getData();

      my $teamrank = 1;
      my @teams    = $doc->findnodes('//groupList/group');
      foreach my $team (@teams) {

        my $id = $team->getAttribute('id');

        my $obj = {
          rank => $teamrank,
        };
        my ($node) = $team->findnodes('name/text()');
        $obj->{'name'} = $node->getData();

        ($node) = $team->findnodes('progress/text()');
        $obj->{'progress'} = $node->getData();

        ($node) = $team->findnodes('memberCount/text()');
        $obj->{'members'} = $node->getData();

        ($node) = $team->findnodes('memberCount/text()');
        $obj->{'members'} = $node->getData();

        $self->{'teams'}{$id} = $obj;
        $teamrank++;
      }
    }
  }

  return $self->{'details'};
}

sub getMembers {
  my ($self, %args) = @_;

  my $url =
    MEMBER_URL . "?challengeID=$self->{'challenge_id'}&confirmedOnly=true";

  if(exists($args{'start'})) {
    if($args{'start'} =~ /^\d+$/o) {
      $url .= "&startidx=$args{'start'}";
    } else {
      warn("Argument: start: must be a number\n");
    }
  }

  if(exists($args{'end'})) {
    if($args{'end'} =~ /^\d+$/o) {
      $url .= "&endidx=$args{'end'}";
    } else {
      warn("Argument: end must be a number\n");
    }
  }

  my $doc = $self->_request($url);
  my ($me) = $doc->findnodes('//currentUser/rank/text()');

  $self->{'rank'} = $me->getData();

  my @retval;
  my @runners = $doc->findnodes('//memberList/member');

  foreach my $dude (@runners) {
    my $obj = {};
    my ($node) = $dude->findnodes('screenName/text()');
    ($node) = $dude->findnodes('email/text()') unless($node);
    $obj->{'name'} = $node->getData();

    ($node) = $dude->findnodes('progress/text()');
    $obj->{'progress'} = $node->getData();

    if($self->isTeam()) {
      ($node) = $dude->findnodes('groupID/text()');
      $obj->{'team'} = $node->getData();
    }

    push(@retval, $obj);
  }

  @retval = sort { $b->{'progress'} <=> $a->{'progress'} } @retval;

  return wantarray ? @retval : \@retval;
}

sub _request {
  my ($self, $url) = @_;

  my $response = $self->{'user_agent'}->get($url);
  my $doc      = $self->{'xp'}->parse_string($response->content());

  return $doc;
}
